#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>

#include "generation.h"

using std::cout;
using std::cin;
using std::stringstream;
using std::string;
using std::endl;

int main(int argc, char** argv){
	int i = stoi(argv[1]);
	stringstream out;
	if(i>1){
		int size = i+i;
		int layer = 0;
		int* cur = new int[size];
		int* next = new int[size];
		
		genvhdltop(i);
		
		for(int j=0; j<size; ++j){
			cur[j]=next[j]=0;
		}
		for(int j=0; j<i*i; ++j){
			int k = j/i + j%i;
			out << genname(k,layer,cur[k]++) << " <= "
					<< "and_result(" << j << ");" << endl;
		}
		while(generate(size, cur, next, out, layer)){
			cout << "-- LAYER " << layer << " --" << endl;
			bool docopy = false;
			for(int k=0; k<size; ++k){
				if(cur[k])
					cout << gensignal(k,layer,cur[k]) << endl;
				if(next[k])
					docopy=true;
			}
			if(docopy){
				delete [] cur;
				cur = next;
				next = new int[size];
				for(int k=0; k<size; ++k)
					next[k]=0;
			}
			
			++layer;
		}
		
		cout << "-- LAYER " << layer << " --" << endl;
		bool docopy = false;
		for(int k=0; k<size; ++k){
			if(cur[k])
				cout << gensignal(k,layer,cur[k]) << endl;
			if(next[k])
				docopy=true;
		}
		if(docopy){
			delete [] cur;
			cur = next;
			next = new int[size];
			for(int k=0; k<size; ++k)
				next[k]=0;
		}
		
		cout << endl << endl << "begin" << endl << endl;
	
		cout << "GEN_AND: for N in 0 to " << i-1 << " generate\n";
		cout << "\tGEN_AND_1: for M in 0 to " << i-1 << " generate\n";
		cout << "\t\tand_result(N*" << i << "+M) <= operand1(N) and operand2(M);\n";
		cout << "\tend generate GEN_AND_1;\n";
		cout << "end generate GEN_AND;\n\n\n";
		
		string s;
		while(getline(out, s)){
			cout << s << endl;
		}
		
		for(int k=0; k<size; ++k){
			cout << "part1(" << k << ") <= " << genname(k, layer, 0) << ";\n";
			if(cur[k]>1)
				cout << "part2(" << k << ") <= " << genname(k, layer, 1) << ";\n";
			else
				cout << "part2(" << k << ") <= \'0\'" << ";\n";
		}
		
		cout << endl << endl;
		
		cout << "product <= part1 + part2;" << endl << endl;
		
		genvhdlend(i);
	}

	
	return 0;
}
